import random
import math
import Parameter

class IndividuoMultiobjetivo(object):
    """description of class"""

    parametros = []
    numParametros = 30
    numCodificacion = 30
    maxVal = 1.0
    currentRank = 0

    diccionarioDominancia = []
    fitnessValues = []

    #----------------------------------------------------------------------
    def __init__(self, _funcionValores, numParametros, numCodificacion, maxVal):
      self.diccionarioDominancia = []
      self.diccionarioDominancia.append(_funcionValores)
      self.fitnessValues = []
      self.numParametros = numParametros
      self.numCodificacion = numCodificacion
      self.maxVal = maxVal
      self.parametros = [Parameter.Parameter(maxVal, numCodificacion) for it in range(numParametros)]
      self.currentRank = 0

    #----------------------------------------------------------------------
    def RandomInit(self):
      for itParam in range(self.numParametros):
        valueList = []
        for it in range(self.numCodificacion):
          if random.uniform(0,1) > 0.5:
            valueList.append(1)
          else:
            valueList.append(0)

        self.parametros[itParam].SetListValues(valueList)
      self.GetFitnesVals()

    #----------------------------------------------------------------------
    def Distancia(self, individuo2):
      sum = 0
      for it in range(len(self.fitnessValues)):
        sum += (self.fitnessValues[it] - individuo2.fitnessValues[it])**2 
  
      return sum**0.5

    #----------------------------------------------------------------------
    def SetParametros(self, parametros):
      self.parametros = parametros
      self.fitnessValues = self.GetFitnesVals()
  
    #----------------------------------------------------------------------
    def GetFitnesVals(self):
      if len(self.fitnessValues) == 0:
        self.fitnessValues = self.diccionarioDominancia[0]([self.parametros[it].GetValue() for it in range(self.numParametros)])
      
      return self.fitnessValues

    #----------------------------------------------------------------------
    def GetSharedFitness(self, nicheCount):
      return (sum(self.fitnessValues))/nicheCount

    #----------------------------------------------------------------------
    def Cruzar(self, pareja):
        punto = random.randrange(self.numParametros -1)
        (paramPuntoHijo1, paramPuntoHijo2) = self.parametros[punto].Cruzar(pareja.parametros[punto])
        hijo1 = IndividuoMultiobjetivo(self.diccionarioDominancia[0], self.numParametros, self.numCodificacion, self.maxVal)
        hijo2 = IndividuoMultiobjetivo(self.diccionarioDominancia[0], self.numParametros, self.numCodificacion, self.maxVal)
        hijo1.SetParametros(self.parametros[:punto] + [paramPuntoHijo1] + pareja.parametros[(punto+1):])
        hijo2.SetParametros(pareja.parametros[:punto] + [paramPuntoHijo2]  + self.parametros[(punto+1):])
        return (hijo1, hijo2)
        
    #----------------------------------------------------------------------
    def CruzarCromosomas(self, pareja):
      params1 = []
      params2 = []
      for it in range(self.numParametros):
        (paramPuntoHijo1, paramPuntoHijo2) = self.parametros[it].Cruzar(pareja.parametros[it])
        params1 += [paramPuntoHijo1]
        params2 += [paramPuntoHijo2]

      hijo1 = IndividuoMultiobjetivo(self.diccionarioDominancia[0], self.numParametros, self.numCodificacion, self.maxVal)
      hijo2 = IndividuoMultiobjetivo(self.diccionarioDominancia[0], self.numParametros, self.numCodificacion, self.maxVal)
      hijo1.SetParametros(params1)
      hijo2.SetParametros(params2)

      return (hijo1, hijo2)
        
    #----------------------------------------------------------------------
    def Mutar(self):
      punto = random.randrange(self.numParametros -1)
      self.parametros[punto].Mutar()
